package zookeeper;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

import util.RandomUtil;

public class SyncTest {

	private static final Log log = LogFactory.getLog(SyncTest.class);

	private static final String lockRoot = "/lockroot/taskA";

	private static ZooKeeper zk = ZooKeeperUtil.initZooKeeper();

	static {
		try {
			Stat stat = zk.exists(lockRoot, false);
			if (stat == null) {
				zk.create(lockRoot, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
			}
		} catch (KeeperException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void doAction(String id) {
		log.info(id + "开始执行任务！");
		try {
			Thread.sleep((RandomUtil.getRandomInt(5)+3) * 1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		log.info(id + "任务执行完毕！");
	}

	public void taskA(String threadID, String id) throws Exception {
		log.info(System.currentTimeMillis() + " " + threadID + "开始执行:" + id);

		try {
			if (checkLock(id) == false) {
				throw new Exception("已有相同ID任务正在执行");
			}
		} catch (KeeperException e) {
			e.printStackTrace();
			throw new Exception("获取锁服务失败");
		} catch (InterruptedException e) {
			e.printStackTrace();
			throw new Exception("获取锁服务失败");
		}
		try {
			doAction(id);
		} finally {
			deleteLock(id);
		}

	}

	private synchronized boolean checkLock(String id) throws KeeperException, InterruptedException {

		Stat stat = zk.exists(lockRoot + "/" + id, false);
		if (stat != null) {
			return false;
		} else {
			zk.create(lockRoot + "/" + id, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
			return true;
		}
	}

	private void deleteLock(String id) {
		try {
			zk.delete(lockRoot + "/" + id, -1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (KeeperException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		final SyncTest st = new SyncTest();
		new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					st.taskA(Thread.currentThread().getName(), "2013");
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		}) {
		}.start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					st.taskA(Thread.currentThread().getName(), "2013");
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		}) {
		}.start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					st.taskA(Thread.currentThread().getName(), "2015");
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		}) {
		}.start();

	}
}
